﻿using Castle.Core.Configuration;
using Castle.Core.Configuration.Xml;
using Inovout.Runtime;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml;

namespace Inovout.Web
{
    internal class ContentResource
    {
        internal bool HasCdnUri
        {
            get { return !string.IsNullOrWhiteSpace(CdnUri); }
        }
        internal string Uri { get; private set; }
        internal string CdnUri { get; private set; }
        internal ContentResource[] IncludeContentResources { get; private set; }
        internal string[] IncludeContentResourceUris
        {
            get { return IncludeContentResources.Select(c => c.Uri).ToArray(); }
        }
        internal static ContentResource[] ScriptResources { get; private set; }
        internal static ContentResource[] StyleResources { get; private set; }
        private static IApplication Application;
        public bool Exists
        {
            get { return IsExists(); }
        }
        private bool IsExists()
        {
            string resouceUri = this.Uri[0].Equals('~') ? this.Uri.Substring(2) : this.Uri.Substring(1);
            return new FileInfo(Path.Combine(HttpRuntime.AppDomainAppPath, resouceUri)).Directory.Exists;
            //return IncludeContentResourceUris.Any(uri => {
            //    string resouceUri = this.Uri[0].Equals('~') ? uri.Substring(1) : uri;
            //    return !File.Exists(Path.Combine(HttpRuntime.AppDomainAppPath, resouceUri));

            //});
        }
        internal static void Load(IApplication application)
        {
            Application = application;
            if (application.IsDebug && File.Exists(Path.Combine(application.Path, "Configs/ContentResource.debug.config")))
            {
                LoadConfig(Path.Combine(application.Path, "Configs/ContentResource.debug.config"));
            }
            else if (File.Exists(Path.Combine(application.Path, "Configs/ContentResource.config")))
            {
                LoadConfig(Path.Combine(application.Path, "Configs/ContentResource.config"));
            }
            else
            {
                StyleResources = new ContentResource[0];
                ScriptResources = new ContentResource[0];
            }
        }
        internal static void LoadConfig(string contentResourceConfigFileName)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(contentResourceConfigFileName);
            IConfiguration contentResourceConfiguration = XmlConfigurationDeserializer.GetDeserializedNode(xmlDocument.DocumentElement);

            StyleResources = ReadStyleConfig(contentResourceConfiguration.Children.SingleOrDefault(c => c.Name.Equals("styles")));
            ScriptResources = ReadScriptConfig(contentResourceConfiguration.Children.SingleOrDefault(c => c.Name.Equals("scripts")));

        }
        internal static ContentResource[] ReadStyleConfig(IConfiguration contentsConfiguration)
        {
            if (contentsConfiguration == null)
            {
                return new ContentResource[0];
            }
            else
            {
                List<ContentResource> contentResources = new List<ContentResource>();
                string themeExpression = "{theme}";
                foreach (IConfiguration contentConfiguration in contentsConfiguration.Children)
                {
                    string uri = contentConfiguration.Attributes["uri"];
                    ContentResource contentResource = null;
                    if (uri.Contains(themeExpression))
                    {
                        string themeFilePath = Path.Combine(Application.Path, @"Styles\Themes\");
                        DirectoryInfo themesDirectory = new DirectoryInfo(themeFilePath);
                        if (themesDirectory.Exists)
                        {
                            foreach (DirectoryInfo directory in themesDirectory.GetDirectories())
                            {
                                contentResource = new ContentResource
                                    {
                                        Uri = uri.Replace(themeExpression, directory.Name),
                                        CdnUri = contentConfiguration.Attributes["cdnUri"],
                                        IncludeContentResources = contentConfiguration.Children.Select
                                        (
                                            c =>
                                                new ContentResource
                                                {
                                                    Uri = c.Attributes["uri"].Replace(themeExpression, directory.Name)
                                                }
                                        ).ToArray()
                                    };
                                contentResources.Add(contentResource);
                            }
                        }
                    }
                    else
                    {
                        contentResource = new ContentResource
                          {
                              Uri = uri,
                              CdnUri = contentConfiguration.Attributes["cdnUri"],
                              IncludeContentResources = ReadStyleConfig(contentConfiguration)
                          };
                        contentResources.Add(contentResource);
                    }
                }

                return contentResources.ToArray();
            }
        }
        internal static ContentResource[] ReadScriptConfig(IConfiguration contentsConfiguration)
        {
            if (contentsConfiguration == null)
            {
                return new ContentResource[0];
            }
            else
            {
                List<ContentResource> contentResources = new List<ContentResource>();
                foreach (IConfiguration contentConfiguration in contentsConfiguration.Children)
                {
                    ContentResource contentResource = new ContentResource { Uri = contentConfiguration.Attributes["uri"], CdnUri = contentConfiguration.Attributes["cdnUri"], IncludeContentResources = ReadScriptConfig(contentConfiguration) };
                    contentResources.Add(contentResource);
                }

                return contentResources.ToArray();
            }
        }
    }
}
